package com.freeleaps.devops

import com.freeleaps.devops.enums.DependenciesManager

/**
 * 依赖解析器类
 * 负责根据不同的编程语言和依赖管理器下载和安装项目依赖
 * 支持多种依赖管理器：PIP、NPM、YARN、PNPM
 * 提供缓存机制以加速后续构建过程
 */
class DependenciesResolver {
  // Jenkins Pipeline的steps对象，用于调用Jenkins内置功能
  def steps
  // 编程语言类型（如Python、JavaScript等）
  def language
  // 是否启用依赖缓存
  def cachingEnabled
  // 依赖管理器类型（PIP、NPM、YARN、PNPM）
  def mgr
  // 工作空间路径，依赖安装的目标目录
  def workspace

  /**
   * 构造函数
   * @param steps Jenkins Pipeline的steps对象
   * @param language 编程语言类型
   * @param workspace 工作空间路径
   */
  DependenciesResolver(steps, language, workspace) {
    this.steps = steps
    this.language = language
    this.workspace = workspace
  }

  /**
   * 启用依赖缓存支持
   * 启用后，依赖包会被缓存，加速后续构建过程
   */
  def enableCachingSupport() {
    this.cachingEnabled = true
  }

  /**
   * 禁用依赖缓存支持
   * 禁用后，每次都会重新下载依赖包
   */
  def disableCachingSupport() {
    this.cachingEnabled = false
  }

  /**
   * 设置依赖管理器
   * @param mgr 依赖管理器类型（PIP、NPM、YARN、PNPM）
   */
  def useManager(DependenciesManager mgr) {
    // 验证依赖管理器是否有效
    if (mgr == DependenciesManager.UNKNOWN) {
      steps.error("Unknown dependencies manager")
    }
    this.mgr = mgr
  }

  /**
   * 获取Node.js版本信息
   * 用于Node.js相关的依赖管理器（NPM、YARN、PNPM）
   */
  def getNodeVersion() {
    def version = steps.sh(script: "node -v", returnStdout: true).trim()
    steps.log.info 'Dependencies Resolver', "Node version is ${version}"
  }

  /**
   * 解析和安装依赖的主要方法
   * 根据配置的依赖管理器类型，执行相应的依赖安装命令
   * 
   * @param configurations 包含依赖配置的Map对象
   *                      - requirementsFile: Python依赖文件路径
   *                      - npmPackageJsonFile: NPM包文件路径
   *                      - yarnPackageJsonFile: YARN包文件路径
   *                      - pnpmPackageJsonFile: PNPM包文件路径
   *                      - name: 组件名称，用于缓存目录命名
   */
  def resolve(configurations) {
    // 验证依赖管理器是否已设置
    if (mgr == null) {
      steps.error("Dependencies manager is not set")
    }

    // 记录依赖解析开始信息
    steps.log.info("Dependencies Resolver","Ready to resolve dependencies for ${language}...")
    steps.log.info("Dependencies Resolver","Using ${mgr.manager} to resolve dependencies...")
    steps.log.info("Dependencies Resolver","Workspace sets to: ${this.workspace}")

    // 记录缓存状态
    if (cachingEnabled) {
      steps.log.info("Dependencies Resolver","Dependencies caching is enabled")
    }

    // 根据依赖管理器类型执行相应的依赖安装逻辑
    switch (mgr) {
      case DependenciesManager.PIP:
        // Python依赖管理器处理
        // 验证requirements.txt文件是否提供
        if (configurations.requirementsFile == null || configurations.requirementsFile.isEmpty()) {
          steps.error("requirementsFile is required when using PIP as dependencies manager")
        }

        def requirementsFile = configurations.requirementsFile

        if (cachingEnabled) {
          // PIP缓存功能（当前被注释掉，因为实现复杂）
          // 理论上可以通过设置pip缓存目录来实现缓存
          // steps.dir(this.workspace) {
          //   steps.cache(maxCacheSize: 512, caches: [[$class: 'ArbitraryFileCache', includes: '**/*', path: ".${configurations.name}-pip-cache", cacheValidityDecidingFile: 'requirements.txt']]) {
          //     steps.sh "mkdir -p .${configurations.name}-pip-cache"
          //     steps.sh "pip config set global.cache-dir '${this.workspace}.${configurations.name}-pip-cache'"
          //     steps.sh "pip install --cache-dir .${configurations.name}-pip-cache -r ${requirementsFile}"
          //   }
          // }
          steps.log.info("Dependencies Resolver","Caching is not supported for PIP")
        } else {
          // 直接安装Python依赖，不使用缓存
          steps.dir(this.workspace) {
            steps.sh "pip install -r ${requirementsFile}"
          }
        }

        break
      case DependenciesManager.NPM:
        // NPM依赖管理器处理
        // 验证package.json文件是否提供
        if (configurations.npmPackageJsonFile == null || configurations.npmPackageJsonFile.isEmpty()) {
          steps.error("npmPackageJsonFile is required when using NPM as dependencies manager")
        }

        def packageJsonFile = configurations.npmPackageJsonFile

        // 获取Node.js版本信息
        this.getNodeVersion()

        if (cachingEnabled) {
          // 使用Jenkins Cache插件进行NPM缓存
          // 需要插件：Pipeline Caching Plugin (pipeline-caching) - 提供steps.cache功能
          steps.dir(this.workspace) {
            steps.cache(maxCacheSize: 2048, caches: [[$class: 'ArbitraryFileCache', includes: '**/*', path: "${steps.env.WORKSPACE}/.${configurations.name}-npm-cache", cacheValidityDecidingFile: 'package-lock.json']]) {
              // 创建缓存目录
              steps.sh "mkdir -p ${steps.env.WORKSPACE}/.${configurations.name}-npm-cache"
              // 使用缓存目录安装依赖，优先使用离线缓存
              steps.sh "npm install --cache ${steps.env.WORKSPACE}/.${configurations.name}-npm-cache --prefer-offline --no-audit"
            }
          }
        } else {
          // 直接安装NPM依赖，不使用缓存
          steps.dir(this.workspace) {
            steps.sh "npm install"
          }
        }

        break
      case DependenciesManager.YARN:
        // YARN依赖管理器处理
        // 验证package.json文件是否提供
        if (configurations.yarnPackageJsonFile == null || configurations.yarnPackageJsonFile.isEmpty()) {
          steps.error("yarnPackageJsonFile is required when using YARN as dependencies manager")
        }

        def packageJsonFile = configurations.yarnPackageJsonFile

        // 获取Node.js版本信息
        this.getNodeVersion()

        // 启用YARN包管理器（通过corepack）
        steps.log.info("Dependencies Resolver","Using YARN as dependencies manager, enable Yarn with corepack...")
        steps.sh "corepack enable yarn && yarn -v"

        if (cachingEnabled) {
          // 使用Jenkins Cache插件进行YARN缓存
          // 需要插件：Pipeline Caching Plugin (pipeline-caching) - 提供steps.cache功能
          steps.dir(this.workspace) {
            steps.cache(maxCacheSize: 2048, caches: [[$class: 'ArbitraryFileCache', includes: '**/*', path: "${steps.env.WORKSPACE}/.${configurations.name}-yarn-cache", cacheValidityDecidingFile: 'yarn.lock']]) {
              // 创建缓存目录（注意：这里有个bug，目录名应该是yarn-cache而不是pnpm-cache）
              steps.sh "mkdir -p ${steps.env.WORKSPACE}/.${configurations.name}-pnpm-cache"
              // 使用缓存目录安装依赖，优先使用离线缓存
              steps.sh "yarn install --cache-folder ${steps.env.WORKSPACE}/.${configurations.name}-pnpm-cache --prefer-offline"
            }
          }
        } else {
          // 直接安装YARN依赖，不使用缓存
          steps.dir(this.workspace) {
            steps.sh "yarn install"
          }
        }

        break
      case DependenciesManager.PNPM:
        // PNPM依赖管理器处理
        // 验证package.json文件是否提供
        if (configurations.pnpmPackageJsonFile == null || configurations.pnpmPackageJsonFile.isEmpty()) {
          steps.error("pnpmPackageJsonFile is required when using PNPM as dependencies manager")
        }

        def packageJsonFile = configurations.pnpmPackageJsonFile

        // 获取Node.js版本信息
        this.getNodeVersion()

        // 启用PNPM包管理器（通过corepack）
        steps.log.info("Dependencies Resolver","Using pnpm as dependencies manager, enable pnpm with corepack...")
        steps.sh "corepack enable pnpm && pnpm -v"

        if (cachingEnabled) {
          // 使用Jenkins Cache插件进行PNPM缓存
          // 需要插件：Pipeline Caching Plugin (pipeline-caching) - 提供steps.cache功能
          steps.dir(this.workspace) {
            steps.cache(maxCacheSize: 2048, caches: [[$class: 'ArbitraryFileCache', includes: '**/*', path: "${steps.env.WORKSPACE}/.${configurations.name}-pnpm-cache", cacheValidityDecidingFile: 'pnpm-lock.yaml']]) {
              // 创建缓存目录
              steps.sh "mkdir -p ${steps.env.WORKSPACE}/.${configurations.name}-pnpm-cache"
              // 使用缓存目录安装依赖，优先使用离线缓存
              steps.sh "pnpm install --store-dir ${steps.env.WORKSPACE}/.${configurations.name}-pnpm-cache --prefer-offline"
            }
          }
        } else {
          // 直接安装PNPM依赖，不使用缓存
          steps.dir(this.workspace) {
            steps.sh "pnpm install"
          }
        }

        break
      default:
        // 不支持的依赖管理器类型
        steps.error("Unsupported dependencies manager")
    }
  }
}